﻿/**
 * \file CStaticMemPool.cc
 * \reversion 0.1
 * \brief 静态内存池，应用于小内存分配的静态内存池
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#ifndef __CSTATIC__MEM__POOL__H
#define __CSTATIC__MEM__POOL__H

#include "CSingletonFactory.h"

/// 返回内存池的空闲内存大小
#define __MEM_POOL_FREE_SIZE(pool) (size_t)((pool ? (pool->_pEnd - pool->_pFreeBeg) : 0))
/// 地址是否在内存池中
#define __ADDR_IS_IN_MEM_POOL(addr, pool) ((addr >= pool._pBeg && addr <= pool._pEnd) ? true : false)
/// 初始化内存池大小（应为__ALIGN_的倍数）
#define __INIT_POOL_SIZE_ (1024 * 1024)

/// 静态大小的内存池定义
/// 非线程安全
class CStaticMemPool
	: public CSingletonFactory<CStaticMemPool>
{
	friend class CSingletonFactory<CStaticMemPool>;

public:
	/// 内存块大小下限
	enum { __ALIGN_ = 8 };
	/// 内存块大小上限
	enum { __MAX_BYTES_ = 128 };
	/// 内存块个数
	enum { __NFREELISTS_NUM_ = __MAX_BYTES_ / __ALIGN_ };
	/// 每次填充的个数
	enum { __FILL_NUM_ = 20 };
	

private:
	/// 内存块定义
	union MemObj
	{
		MemObj()
		{
			_pFreeListLink = NULL;
		}

		union MemObj *_pFreeListLink;	/// 未分配指向下一个块
		char _ClientData[1];			/// 分配后标识内存指针
	};

	/// 内存块头结点定义
	struct MemblcHead
	{
		MemblcHead()
		{
			_pHead = NULL;
			_count = 0;
		}

		MemObj* volatile _pHead;		/// 头结点
		size_t volatile _count;			/// 引用计数（用于查询内存泄露）
	};

	/// 链表内存池定义
	struct MemPool
	{
		MemPool()
		{
			_pBeg = NULL;
			_pFreeBeg = NULL;
			_pEnd = NULL;
			_pNext = NULL;
		}

		char* _pBeg;		/// 内存池开始地址
		char* _pFreeBeg;	/// 内存池可用内存开始地址
		char* _pEnd;		/// 内存池结束地址
		MemPool* _pNext;	/// 下一个内存池地址
	};

private:
	CStaticMemPool();
	~CStaticMemPool();

private:
	/// 上调到8的倍数
	size_t RoundUp(size_t _bytes);

	/// 根据块大小，计算块索引
	size_t FreeListIndex(size_t _bytes);

	/// 初始化
	void InitMemPool();

	/// 填充块
	bool Refill(size_t _size);

public:
	/// 申请一段内存
	void* Allocate(size_t _size);

	/// 释放一段内存
	bool Deallocate(void *p, size_t _size);

	/// 打印各个内存块的使用情况，关机程序时，打印可查询内存泄露
	void PrintMemBlock();

private:
	MemblcHead volatile m_FreeList[__NFREELISTS_NUM_];		/// 内存块表

	MemPool m_headPool;										/// 内存池
	MemPool* m_pCurPool;									/// 当前内存池
};

#endif	/// __CSTATIC__MEM__POOL__H
